﻿/*  ----------------------------------------------------------------------------
 *  SysServer
 *  ----------------------------------------------------------------------------
 *  File:       Program.cs
 *  Creater:     SEEN\MistSeen
 *  ----------------------------------------------------------------------------
 *  $Date: 2010-09-06 10:36:01 +0000 (Mon, 06 Sep 2010) $
 *  $Rev: 15 $
 *  $Author: ScorDeity $
 *  $URL: http://sysserver.googlecode.com/svn/trunk/src/SysServerSample/Program.cs $
 *  $Id: Program.cs 15 2010-09-06 10:36:01Z ScorDeity $
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace SysServerSample
{
    using SysServer.Threading;
    using System.Threading;
    using System.Runtime.InteropServices;
    using Microsoft.Win32.SafeHandles;
    class Program
    {
        static void Main(string[] args)
        {
            // Create the MSSQL IOCP Thread Pool
            IOCPThreadPool pThreadPool = new IOCPThreadPool(0, 4, 10, new IOCPThreadPool.FuncHandle(IOCPThreadFunction));
            pThreadPool.PostEvent(10);
            pThreadPool.PostEvent(20);
            pThreadPool.PostEvent(30);
            pThreadPool.PostEvent(100);
            pThreadPool.PostEvent(30);
            pThreadPool.PostEvent(100);

            for (int i = 0; i < 10; i++)
            {
                pThreadPool.PostEvent(100 * i);
            }
            pThreadPool.PostEvent();

            TestIOCPApi();

            Console.ReadLine();
        }
        static public void IOCPThreadFunction(Int32 iValue)
        {
            try
            {
                Console.WriteLine("Value: {0}", iValue);
            }
            catch (Exception pException)
            {
                Console.WriteLine(pException.Message);
            }
        }

        public static unsafe void TestIOCPApi()
        {
            var CompletionPort = SysServer.IOCPEx.CreateIoCompletionPort(new IntPtr(-1), IntPtr.Zero, IntPtr.Zero, 1);
            if (CompletionPort.IsInvalid)
            {
                Console.WriteLine("CreateIoCompletionPort 出错:{0}", Marshal.GetLastWin32Error());
            }
            var thread = new Thread(ThreadProc);
            thread.Start(CompletionPort);

            var PerIOData = new PER_IO_DATA();
            var gch = GCHandle.Alloc(PerIOData);
            PerIOData.Data = "hi,我是蛙蛙王子，你是谁？";
            Console.WriteLine("{0}-主线程发送数据", Thread.CurrentThread.GetHashCode());
            SysServer.IOCPEx.PostQueuedCompletionStatus(CompletionPort, (uint)sizeof(IntPtr), IntPtr.Zero, (IntPtr)gch);

            var PerIOData2 = new PER_IO_DATA();
            var gch2 = GCHandle.Alloc(PerIOData2);
            PerIOData2.Data = "关闭工作线程吧";
            Console.WriteLine("{0}-主线程发送数据", Thread.CurrentThread.GetHashCode());
            SysServer.IOCPEx.PostQueuedCompletionStatus(CompletionPort, 4, IntPtr.Zero, (IntPtr)gch2);
            Console.WriteLine("主线程执行完毕");
            Console.ReadKey();
        }
        static void ThreadProc(object CompletionPortID)
        {

            

            var CompletionPort = (SafeFileHandle)CompletionPortID;

            while (true)
            {
                uint BytesTransferred;
                IntPtr PerHandleData;
                IntPtr lpOverlapped;
                Console.WriteLine("{0}-工作线程准备接受数据", Thread.CurrentThread.GetHashCode());
                SysServer.IOCPEx.GetQueuedCompletionStatus(CompletionPort, out BytesTransferred,
                                          out PerHandleData, out lpOverlapped, 0xffffffff);
                if (BytesTransferred <= 0)
                    continue;
                GCHandle gch = GCHandle.FromIntPtr(lpOverlapped);
                var per_HANDLE_DATA = (PER_IO_DATA)gch.Target;
                Console.WriteLine("{0}-工作线程收到数据：{1}", Thread.CurrentThread.GetHashCode(), per_HANDLE_DATA.Data);
                gch.Free();
                if (per_HANDLE_DATA.Data != "关闭工作线程吧") continue;
                Console.WriteLine("收到退出指令，正在退出");
                CompletionPort.Dispose();
                break;
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        class PER_IO_DATA
        {
            public string Data;
        }
    }
}